﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Configuration;
using System.Net.Mail;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Configuration;
using System.Web.UI;
using System.Web.UI.WebControls;
using Image = System.Drawing.Image;

namespace LOGISTCBUS.Entities
{
    public class WebHelpers : Page
    {
        #region [ Fields ]

        private static WebHelpers instance;

        #endregion [ Fields ]

        #region [ Properties ]

        /// <summary>
        /// Gets the single instance.
        /// </summary>
        /// <value>The single instance.</value>
        public static WebHelpers SingleInstance
        {
            get
            {
                if (instance == null)
                {
                    return instance = new WebHelpers();
                }
                return instance;
            }
        }

        /// <summary>
        /// Gets the session main.
        /// </summary>
        /// <value>The session main.</value>
        public static System.Web.SessionState.HttpSessionState SessionMain
        {
            get
            {
                return HttpContext.Current.Session;
            }
        }

        #endregion [ Properties ]

        #region [ Eventos Overrides ]

        protected override void OnError(EventArgs e)
        {
            HttpContext ctx = HttpContext.Current;
            if (!ctx.Server.GetLastError().Message.ToLower().Contains("reference not set"))
            {
                var script = new StringBuilder();

                script.Append("<script language=\"javascript\">\n");
                //script.Append("alert('" + HttpContext.Current.Request.Url + "');");
                //script.Append("window.open('~/Errors.aspx','janela','width=450, height=250');");

                script.Append("var rootPath = '" + Request.ApplicationPath + "';");
                script.Append("if (rootPath == '/')");
                script.Append("    rootPath = '';");
                script.Append("window.location.href = rootPath + '/Errors.aspx';");
                //script.Append("window.history.back(1);");
                script.Append("</script>");

                Session["Exception"] = ctx.Server.GetLastError();

                //Page.ClientScript.RegisterClientScriptBlock(base.GetType(), "abrirPopup", script.ToString());

                //base.RegisterClientScriptBlock("script", script.ToString());

                ctx.Response.Write(script.ToString());
                //    ctx.Response.Write(errorInfo);

                // --------------------------------------------------
                // To let the page finish running we clear the error
                // --------------------------------------------------
                ctx.Server.ClearError();
                //base.OnError(e);
            }
            else
            {
                Response.Redirect(ctx.Request.Path.Split('/')[1] + "/Default.aspx", false);
            }
        }

        #endregion [ Eventos Overrides ]

        #region [ Métodos para Controles e afins ]

        /// <summary>
        /// Método para deixar o campo UPPERCASE
        /// </summary>
        /// <param name="campo"></param>
        public void Uppercase(TextBox campo)
        {
            campo.Style.Add("text-transform", "uppercase");
        }

        /// <summary>
        /// Método para Definir um Button como Padrão após pressionar o Enter...
        /// </summary>
        /// <param name="textBox"></param>
        /// <param name="button"></param>
        public static void SetDefaultButton(TextBox textBox, Button button)
        {
            textBox.Attributes.Add("onkeydown", "if(event.which || event.keyCode){if ((event.which == 13) || (event.keyCode == 13)) {document.getElementById('" + button.ClientID + "').click(); return false;}} else {return true}; ");
        }

        /// <summary>
        /// Sets the default button generics.{ Necessário JQuery }
        /// </summary>
        /// <param name="textBox">The text box.</param>
        /// <param name="button">The button.</param>
        public static void SetDefaultButtonGenerics(WebControl textBox, WebControl button)
        {
            textBox.Attributes.Add("onkeydown", "if(event.which || event.keyCode){if ((event.which == 13) || (event.keyCode == 13)) { if ($('#" + button.ClientID + "').prop('href').indexOf('javascript:') === 0) { window.location = $('#" + button.ClientID + "').prop('href'); } else { $('#" + button.ClientID + "').click(); } return false;}} else {return true}; ");
        }

        public static void Confirmacao(WebControl controle, String mensagemConfirmacao)
        {
            controle.Attributes.Add("onclick", "return confirm('" + mensagemConfirmacao + "');");
        }

        /// <summary>
        /// Método para setar um timeout para efetuar determinada tarefa..
        /// </summary>
        /// <param name="currentPage">The current page.</param>
        /// <param name="timeout">Miliseconds</param>
        /// <param name="control">Control</param>
        /// <param name="urlToRedirect">The URL to redirect.</param>
        public void SetTimout(Page currentPage, Int32 timeout, Control control, String urlToRedirect)
        {
            String script = "<script type=\"text/javascript\" language=\"javascript\">\n";
            script += "//function redirect()\n";
            script += "//{\n";
            script += "//    document.forms[0].action = '" + urlToRedirect + "';\n";
            script += "//    document.forms[0].method = 'POST';\n";
            script += "//    document.forms[0].submit();\n";
            script += "//}\n\n";
            script += "function timedMsg()\n";
            script += "{\n";
            script += "    //var t = setTimeout(redirect()," + timeout + ");\n";
            script += "    var t = setTimeout(\"document.location.href='" + urlToRedirect + "'\"," + timeout + ");\n";
            script += "}\n";
            script += "timedMsg();";
            script += "</script>";

            currentPage.ClientScript.RegisterStartupScript(control.GetType(), "setTimout", script, true);
            //System.Web.UI.ScriptManager.RegisterStartupScript(control, control.GetType(), "setTimout", script, true);
        }

        #endregion [ Métodos para Controles e afins ]

        #region [ Métodos Utilizados para DropDownLists, CheckBoxLists, RadioButtonLists e afins ]

        /// <summary>
        /// Binds the dropdown with enum.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <param name="myEnum">My enum.</param>
        public static void BindDropdownWithEnum(ref DropDownList drop, Type myEnum)
        {
            ListItem item;
            drop.Items.Clear();

            var names = Enum.GetNames(myEnum);
            for (int i = 0; i <= names.GetUpperBound(0); i++)
            {
                item = new ListItem
                {
                    Text = GetEnumDescription((Enum)Enum.Parse(myEnum, names[i])),
                    Value = Convert.ToInt32(Enum.Parse(myEnum, names[i])).ToString()
                };

                drop.Items.Add(item);
            }
        }

        /// <summary>
        /// Binds the dropdown with enum.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <param name="myEnum">My enum.</param>
        /// <param name="AddItemSelecione">if set to <c>true</c> [add item selecione].</param>
        /// <param name="firstItemText">The first item text.</param>
        public static void BindDropdownWithEnum(ref DropDownList drop, Type myEnum, bool AddItemSelecione, String firstItemText)
        {
            drop.Items.Clear();
            String[] names = Enum.GetNames(myEnum);
            for (int i = 0; i <= names.GetUpperBound(0); i++)
            {
                var item = new ListItem
                {
                    Text = GetEnumDescription((Enum)Enum.Parse(myEnum, names[i])),
                    Value = Convert.ToInt32(Enum.Parse(myEnum, names[i])).ToString()
                };

                drop.Items.Add(item);
            }
            if (AddItemSelecione)
            {
                drop.Items.Insert(0, new ListItem(firstItemText, ""));
            }
        }

        /// <summary>
        /// Binds the radio with enum.
        /// </summary>
        /// <param name="radio">The radio.</param>
        /// <param name="myEnum">My enum.</param>
        public static void BindRadioWithEnum(ref RadioButtonList radio, Type myEnum)
        {
            ListItem item;
            radio.Items.Clear();
            var names = Enum.GetNames(myEnum);
            for (int i = 0; i <= names.GetUpperBound(0); i++)
            {
                item = new ListItem
                {
                    Text = GetEnumDescription((Enum)Enum.Parse(myEnum, names[i])),
                    Value = Convert.ToInt32(Enum.Parse(myEnum, names[i])).ToString()
                };

                radio.Items.Add(item);
            }
        }

        /// <summary>
        /// Binds the dropdown with days.
        /// </summary>
        /// <param name="drop">The drop.</param>
        /// <param name="year">The year.</param>
        /// <param name="month">The month.</param>
        public static void BindDropdownWithDays(ref DropDownList drop, Int32 year, Int32 month)
        {
            int i;
            var days = new List<Int32>();

            switch (month)
            {
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    {
                        for (i = 1; i <= 31; i++)
                            days.Add(i);
                    }
                    break;
                case 2:
                    // Verificar
                    if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
                    {
                        for (i = 1; i <= 29; i++)
                            days.Add(i);
                    }
                    else
                    {
                        for (i = 1; i <= 28; i++)
                            days.Add(i);
                    }
                    break;
                case 4:
                case 6:
                case 9:
                case 11:
                    {
                        for (i = 1; i <= 30; i++)
                            days.Add(i);
                    }
                    break;
            }
            drop.DataSource = days;
            drop.DataBind();
        }

        /// <summary>
        /// Método para popular Dropdownlist
        /// </summary>
        /// <param name="drop"></param>
        /// <param name="dataSource"></param>
        /// <param name="dataTextField"></param>
        /// <param name="dataValueField"></param>
        public static void BindDropDown(DropDownList drop, object dataSource, String dataTextField, String dataValueField)
        {
            drop.Items.Clear();
            drop.DataSource = dataSource;
            drop.DataValueField = dataValueField;
            drop.DataTextField = dataTextField;
            drop.DataBind();
        }

        /// <summary>
        /// Método para popular Dropdownlist
        /// </summary>
        /// <param name="drop">Dropdownlist</param>
        /// <param name="dataSource">Datasource</param>
        /// <param name="dataTextField">Text</param>
        /// <param name="dataValueField">Value</param>
        /// <param name="selectedValue">Texto Padrão value ""</param>
        public static void BindDropDown(DropDownList drop, object dataSource, String dataTextField, String dataValueField, String selectedValue)
        {
            drop.Items.Clear();
            drop.DataSource = dataSource;
            drop.DataValueField = dataValueField;
            drop.DataTextField = dataTextField;
            drop.DataBind();
            // Inserir item padrão
            drop.Items.Insert(0, new ListItem(selectedValue, ""));
        }

        /// <summary>
        /// Binds the radio.
        /// </summary>
        /// <param name="radio">The radio.</param>
        /// <param name="dataSource">The data source.</param>
        /// <param name="dataTextField">The data text field.</param>
        /// <param name="dataValueField">The data value field.</param>
        public static void BindRadio(RadioButtonList radio, object dataSource, String dataTextField, String dataValueField)
        {
            radio.DataSource = dataSource;
            radio.DataValueField = dataValueField;
            radio.DataTextField = dataTextField;
            radio.DataBind();
        }

        /// <summary>
        /// Binds the radio.
        /// </summary>
        /// <param name="radio">The radio.</param>
        /// <param name="dataSource">The data source.</param>
        /// <param name="dataTextField">The data text field.</param>
        /// <param name="dataValueField">The data value field.</param>
        /// <param name="selectedValue">The selected value.</param>
        public static void BindRadio(RadioButtonList radio, object dataSource, String dataTextField, String dataValueField, String selectedValue)
        {
            radio.DataSource = dataSource;
            radio.DataValueField = dataValueField;
            radio.DataTextField = dataTextField;
            radio.DataBind();
            // Selecionar item
            if (radio.Items.FindByValue(selectedValue) != null)
                radio.Items.FindByValue(selectedValue).Selected = true;
        }

        #endregion [ Métodos Utilizados para DropDownLists, CheckBoxLists, RadioButtonLists e afins ]

        #region [ Métodos para se Trabalhar com Enumeradores ]

        /// <summary>
        /// Gets the enum description.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static String GetEnumDescription(Enum value)
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
                    typeof(DescriptionAttribute), false);

            return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
        }

        #endregion [ Métodos para se Trabalhar com Enumeradores ]

        #region [ Métodos para se Trabalhar com GridViews ]

        /// <summary>
        /// Loads the grid.
        /// </summary>
        /// <param name="gridView">The grid view.</param>
        public static void LoadGrid(object gridView)
        {
            var grv = (GridView)gridView;
            LoadGrid(gridView, Get(GetID(grv)));
        }

        /// <summary>
        /// Loads the grid.
        /// </summary>
        /// <param name="gridView">The grid view.</param>
        /// <param name="dataSource">The data source.</param>
        public static void LoadGrid(object gridView, object dataSource)
        {
            var gdv = (GridView)gridView;

            if (gdv.RowStyle.CssClass != string.Empty
                || gdv.HeaderStyle.CssClass != string.Empty)
            {
                for (int i = 0; i < gdv.Columns.Count; i++)
                {
                    if (gdv.Columns[i].ItemStyle.CssClass == string.Empty)
                        gdv.Columns[i].ItemStyle.CssClass = gdv.RowStyle.CssClass;

                    if (gdv.Columns[i].HeaderStyle.CssClass == string.Empty)
                        gdv.Columns[i].HeaderStyle.CssClass = gdv.HeaderStyle.CssClass;
                }

                gdv.RowStyle.CssClass = string.Empty;
                gdv.HeaderStyle.CssClass = string.Empty;
            }

            gdv.DataSource = dataSource;
            gdv.DataBind();

            if (gdv.AllowPaging || gdv.AllowSorting)
            {
                HttpContext.Current.Session.Add(GetID(gdv), dataSource);

                if (gdv.AllowPaging)
                    gdv.PageIndexChanging += PageIndexChangingGrid;

                if (gdv.AllowSorting)
                    gdv.Sorting += SortingGrid;
            }
        }

        /// <summary>
        /// Pages the index changing grid.
        /// </summary>
        /// <param name="gridview">The gridview.</param>
        /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewPageEventArgs"/> instance containing the event data.</param>
        public static void PageIndexChangingGrid(object gridview, GridViewPageEventArgs e)
        {
            PageIndexChangingGrid(gridview, e.NewPageIndex);
        }

        /// <summary>
        /// Pages the index changing grid.
        /// </summary>
        /// <param name="gridview">The gridview.</param>
        /// <param name="NewPageIndex">New index of the page.</param>
        public static void PageIndexChangingGrid(object gridview, int NewPageIndex)
        {
            var gdv = (GridView)gridview;
            if (NewPageIndex < gdv.PageCount)
            {
                gdv.PageIndex = NewPageIndex;
            }
            else
            {
                gdv.PageIndex = gdv.PageCount > 0 ? gdv.PageCount - 1 : 0;
            }

            if (Exists(GetID(gdv)))
                LoadGrid(gdv);

        }

        /// <summary>
        /// Sortings the grid.
        /// </summary>
        /// <param name="gridView">The grid view.</param>
        /// <param name="e">The <see cref="System.Web.UI.WebControls.GridViewSortEventArgs"/> instance containing the event data.</param>
        public static void SortingGrid(object gridView, GridViewSortEventArgs e)
        {
            var grv = (GridView)gridView;
            if (grv.Attributes["sortexpression"] != e.SortExpression)
            {
                grv.Attributes["sortexpression"] = e.SortExpression;
                grv.Attributes["sortorder"] = "ASC";
            }
            else
            {
                grv.Attributes["sortorder"] = (grv.Attributes["sortorder"] == "ASC") ? "DESC" : "ASC";
            }
        }

        /// <summary>
        /// Sortings the grid.
        /// </summary>
        /// <param name="sortExpression">The sort expression.</param>
        /// <param name="direction">The direction.</param>
        /// <param name="grv">The GRV.</param>
        /// <param name="dataSource">The data source.</param>
        public static void SortingGrid(String sortExpression, String direction, GridView grv, object dataSource)
        {
            var dt = (DataTable)dataSource;
            var dv = new DataView(dt) { Sort = sortExpression + direction };

            grv.DataSource = dv;
            grv.DataBind();
        }

        /// <summary>
        /// Gets the ID.
        /// </summary>
        /// <param name="gridview">The gridview.</param>
        /// <returns></returns>
        public static string GetID(object gridview)
        {
            var gdv = (GridView)gridview;
            return gdv.UniqueID + gdv.ClientID;
        }

        /// <summary>
        /// Retorna um objeto em sessão caso o mesmo exista...
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Object Get(String name)
        {
            if (Exists(name))
                return SessionMain[name];
            return null;
        }

        /// <summary>
        /// Existses the specified name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static bool Exists(string name)
        {
            if (SessionMain != null)
                return (SessionMain[name] != null);
            return false;
        }

        #endregion [ Métodos para se Trabalhar com GridViews ]

        #region [ Métodos para trabalhar com QueryString ]

        /// <summary>
        /// Method to verify existence and content of objects
        /// </summary>
        /// <param name="ParamName">Parameter Name</param>
        /// <returns></returns>
        public String RequestParam(String ParamName)
        {
            String Result = String.Empty;

            if (Context.Request.Form.Count != 0)
            {
                Result = Convert.ToString(Context.Request.Form[ParamName]);
            }
            else if (Context.Request.QueryString.Count != 0)
            {
                Result = Convert.ToString(Context.Request.QueryString[ParamName]);
            }

            return (Result == null) ? String.Empty : Result.Trim();
        }

        /// <summary>
        /// Method basic to encrypt a URL
        /// </summary>
        /// <param name="url">url</param>
        /// <returns>Encrypt Uurl</returns>
        public String EncryptUrl(String url)
        {
            Byte[] bytesUrl = Encoding.ASCII.GetBytes(url);
            String encryptedUrl = Convert.ToBase64String(bytesUrl);
            return encryptedUrl;
        }

        /// <summary>
        /// Method basic to decrypt a URL
        /// </summary>
        /// <param name="url">url</param>
        /// <returns>Decrypt Url</returns>
        public string DecryptUrl(String url)
        {
            Byte[] bytesUrl = Convert.FromBase64String(url);
            String decryptedUrl = Encoding.ASCII.GetString(bytesUrl);
            return decryptedUrl;
        }

        /// <summary>
        /// It verifies if it exists QueryString, if to exist returns a whole number
        /// </summary>
        /// <param name="queryStr">Request.QueryString or Context.Request.QueryString</param>
        /// <returns>Int32 Id</returns>
        public Int32 GetQueryString(System.Collections.Specialized.NameValueCollection queryStr)
        {
            Int32 id = 0;
            if (queryStr.Count != 0)
            {
                String[] arg = DecryptUrl(queryStr.ToString().Replace("%3d", "=")).Split(new[] { '=', '&' });
                id = Convert.ToInt32(arg[1]);
            }
            return id;
        }

        /// <summary>
        /// It verifies if it exists QueryString, if to exist returns a position informed in String
        /// </summary>
        /// <param name="queryStr"></param>
        /// <param name="position">Position in the QueryString</param>
        /// <returns></returns>
        public String GetQueryString(System.Collections.Specialized.NameValueCollection queryStr, Int32 position)
        {
            String value = String.Empty;
            if (queryStr.Count != 0)
            {
                String[] strArray = DecryptUrl(queryStr.ToString().Replace("%3d", "=")).Split(new[] { '=', '&' });

                if (strArray.Length >= 2)
                {
                    if (position % 2 == 0)
                        position = position + 1;

                    if (position <= strArray.Length)
                        value = strArray[position];
                }
            }
            return value;
        }

        /// <summary>
        /// Gets the query string.
        /// </summary>
        /// <param name="queryString">The query string.</param>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public String GetQueryString(System.Collections.Specialized.NameValueCollection queryString, String key)
        {
            if (queryString.Count != 0)
            {
                var strArray = DecryptUrl(queryString.ToString().Replace("%3d", "=")).Split(new[] { '&' });
                if (strArray.Length > 0)
                {
                    return (from query in strArray where query.Contains(key) select query.Split(new[] { '=' }).Last()).FirstOrDefault();
                }
            }
            return String.Empty;
        }

        /// <summary>
        /// Add or update a parameter in the QueryString
        /// </summary>
        /// <param name="querystring"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string AddParameterToQueryString(string querystring, string name, string value)
        {
            if (querystring != string.Empty)
            {
                if (Regex.IsMatch(querystring, @"(&|\?)" + name + @"=[A-Za-z0-9]+"))
                    return Regex.Replace(querystring, name + @"=\d\d?", name + "=" + value);

                return querystring + "&" + name + "=" + value;
            }
            return "?" + name + "=" + value;
        }

        #endregion [ Métodos para trabalhar com QueryString ]

        #region [ Métodos para se trabalhar com String ]

        /// <summary>
        /// Replaces the custom error message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public static String ReplaceCustomErrorMessage(String message)
        {
            if (!String.IsNullOrWhiteSpace(message))
            {
                if (message.Contains("*"))
                {
                    message = message.Replace("*", "");
                }
                if (message.Contains(":"))
                {
                    message = message.Replace(":", "");
                }
                return message;
            }
            return String.Empty;
        }

        #endregion [ Métodos para se trabalhar com String ]

        #region [ RandomPassword ]

        // Define default min and max password lengths.
        //private static int DEFAULT_MIN_PASSWORD_LENGTH = 8;
        //private static int DEFAULT_MAX_PASSWORD_LENGTH = 10;

        // Define supported password characters divided into groups.
        // You can add (or remove) characters to (from) these groups.
        private const string PASSWORD_CHARS_LCASE = "abcdefgijkmnopqrstwxyz";
        private const string PASSWORD_CHARS_UCASE = "ABCDEFGHJKLMNPQRSTWXYZ";
        private const string PASSWORD_CHARS_NUMERIC = "23456789";
        private const string PASSWORD_CHARS_SPECIAL = "*&";    // "*$-+?_&=!%{}/"

        /// <summary>
        /// Generates a random password of the exact length.
        /// </summary>
        /// <param name="length">
        /// Exact password length.
        /// </param>
        /// <returns>
        /// Randomly generated password.
        /// </returns>
        public static string Generate(int length)
        {
            return Generate(length, length);
        }

        /// <summary>
        /// Generates a random password. 8-10
        /// </summary>
        /// <param name="minLength">
        /// Minimum password length.
        /// </param>
        /// <param name="maxLength">
        /// Maximum password length.
        /// </param>
        /// <returns>
        /// Randomly generated password.
        /// </returns>
        /// <remarks>
        /// The length of the generated password will be determined at
        /// random and it will fall with the range determined by the
        /// function parameters.
        /// </remarks>
        public static string Generate(int minLength, int maxLength)
        {
            // Make sure that input parameters are valid.
            if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
                return null;

            // Create a local array containing supported password characters
            // grouped by types. You can remove character groups from this
            // array, but doing so will weaken the password strength.
            char[][] charGroups = new[]
                                      {
                                          PASSWORD_CHARS_LCASE.ToCharArray(),
                                          PASSWORD_CHARS_UCASE.ToCharArray(),
                                          PASSWORD_CHARS_NUMERIC.ToCharArray(),
                                          PASSWORD_CHARS_SPECIAL.ToCharArray()
                                      };

            // Use this array to track the number of unused characters in each
            // character group.
            int[] charsLeftInGroup = new int[charGroups.Length];

            // Initially, all characters in each group are not used.
            for (int i = 0; i < charsLeftInGroup.Length; i++)
                charsLeftInGroup[i] = charGroups[i].Length;

            // Use this array to track (iterate through) unused character groups.
            int[] leftGroupsOrder = new int[charGroups.Length];

            // Initially, all character groups are not used.
            for (int i = 0; i < leftGroupsOrder.Length; i++)
                leftGroupsOrder[i] = i;

            // Because we cannot use the default randomizer, which is based on the
            // current time (it will produce the same "random" number within a
            // second), we will use a random number generator to seed the
            // randomizer.

            // Use a 4-byte array to fill it with random bytes and convert it then
            // to an integer value.
            byte[] randomBytes = new byte[4];

            // Generate 4 random bytes.
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(randomBytes);

            // Convert 4 bytes into a 32-bit integer value.
            int seed = (randomBytes[0] & 0x7f) << 24 |
                       randomBytes[1] << 16 |
                       randomBytes[2] << 8 |
                       randomBytes[3];

            // Now, this is real randomization.
            Random random = new Random(seed);

            // This array will hold password characters.
            char[] password;

            // Allocate appropriate memory for the password.
            if (minLength < maxLength)
                password = new char[random.Next(minLength, maxLength + 1)];
            else
                password = new char[minLength];

            // Index of the next character to be added to password.
            int nextCharIdx;

            // Index of the next character group to be processed.
            int nextGroupIdx;

            // Index which will be used to track not processed character groups.
            int nextLeftGroupsOrderIdx;

            // Index of the last non-processed character in a group.
            int lastCharIdx;

            // Index of the last non-processed group.
            int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;

            // Generate password characters one at a time.
            for (int i = 0; i < password.Length; i++)
            {
                // If only one character group remained unprocessed, process it;
                // otherwise, pick a random character group from the unprocessed
                // group list. To allow a special character to appear in the
                // first position, increment the second parameter of the Next
                // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
                if (lastLeftGroupsOrderIdx == 0)
                    nextLeftGroupsOrderIdx = 0;
                else
                    nextLeftGroupsOrderIdx = random.Next(0,
                                                         lastLeftGroupsOrderIdx);

                // Get the actual index of the character group, from which we will
                // pick the next character.
                nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];

                // Get the index of the last unprocessed characters in this group.
                lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;

                // If only one unprocessed character is left, pick it; otherwise,
                // get a random character from the unused character list.
                if (lastCharIdx == 0)
                    nextCharIdx = 0;
                else
                    nextCharIdx = random.Next(0, lastCharIdx + 1);

                // Add this character to the password.
                password[i] = charGroups[nextGroupIdx][nextCharIdx];

                // If we processed the last character in this group, start over.
                if (lastCharIdx == 0)
                    charsLeftInGroup[nextGroupIdx] =
                        charGroups[nextGroupIdx].Length;
                // There are more unprocessed characters left.
                else
                {
                    // Swap processed character with the last unprocessed character
                    // so that we don't pick it until we process all characters in
                    // this group.
                    if (lastCharIdx != nextCharIdx)
                    {
                        char temp = charGroups[nextGroupIdx][lastCharIdx];
                        charGroups[nextGroupIdx][lastCharIdx] =
                            charGroups[nextGroupIdx][nextCharIdx];
                        charGroups[nextGroupIdx][nextCharIdx] = temp;
                    }
                    // Decrement the number of unprocessed characters in
                    // this group.
                    charsLeftInGroup[nextGroupIdx]--;
                }

                // If we processed the last group, start all over.
                if (lastLeftGroupsOrderIdx == 0)
                    lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
                // There are more unprocessed groups left.
                else
                {
                    // Swap processed group with the last unprocessed group
                    // so that we don't pick it until we process all groups.
                    if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
                    {
                        int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
                        leftGroupsOrder[lastLeftGroupsOrderIdx] =
                            leftGroupsOrder[nextLeftGroupsOrderIdx];
                        leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
                    }
                    // Decrement the number of unprocessed groups.
                    lastLeftGroupsOrderIdx--;
                }
            }

            // Convert password characters into a string and return the result.
            return new string(password);
        }

        #endregion

        #region [ Métodos para Tratamento de Imagens ]

        public static Byte[] ImageToByteArray(String strImage)
        {
            Image img = Image.FromFile(strImage);
            var mem = new MemoryStream();
            //String nameFile = strImage.Split('\\').GetValue(strImage.Split('\\').Length - 1).ToString();

            img.Save(mem, System.Drawing.Imaging.ImageFormat.Jpeg);
            mem.Flush();

            var arrayImagem = new Byte[mem.Length];
            mem.Seek(0, SeekOrigin.Begin);
            mem.Read(arrayImagem, 0, arrayImagem.Length);
            mem.Close();

            return arrayImagem;
        }

        public static Image ByteArrayToImage(Byte[] objImagem)
        {
            var mem = new MemoryStream();
            Byte[] arrayImagem = objImagem;

            mem.Write(arrayImagem, 0, arrayImagem.Length);
            Image img = Image.FromStream(mem);
            //img.Save(imageUrl, ImageFormat.Jpeg);

            mem.Close();

            return img;
        }

        public static void ByteArrayToImage(Byte[] objImagem, String imageUrl)
        {
            var mem = new MemoryStream();
            Byte[] arrayImagem = objImagem;

            mem.Write(arrayImagem, 0, arrayImagem.Length);
            Image img = Image.FromStream(mem);
            img.Save(imageUrl, System.Drawing.Imaging.ImageFormat.Jpeg);

            mem.Close();

            //return img;
        }

        public static void ResizeImage(Size original, Size newSize)
        {
            // TODO: Testar esse método

            // Define o melhor tamanho para a nova imagem, de acordo com a 
            // proporção entre largura e altura da imagem original 

            var proporcaoOriginal = ((original.Height * 100) / original.Width) / 100;
            var novoTamanho = new Size();
            if (proporcaoOriginal > 1)
            {
                proporcaoOriginal = ((original.Width * 100) / original.Height) / 100;
                novoTamanho.Height = newSize.Height;

                novoTamanho.Width = newSize.Height * proporcaoOriginal;
            }
            else
            {
                novoTamanho.Width = newSize.Width;
                novoTamanho.Height = newSize.Width * proporcaoOriginal;
            }
            //Response.Write("Tamanho original:  " & Original.Width & "x" & Original.Height & "");
            //Response.Write("Novo Tamanho: " & NovoTamanho.Width & "x" & NovoTamanho.Height & "");

        }

        #endregion [ Métodos para Tratamento de Imagens ]

        #region [ Métodos para envio de Email ]

        /// <summary>
        /// Method to Send Basic Mail
        /// <seealso cref="http://www.systemnetmail.com/"/>
        /// </summary>
        /// <param name="from">De:</param>
        /// <param name="friendlyName">Joselito Sem ...</param>
        /// <param name="to">Para:</param>
        /// <param name="subject">Assunto:</param>
        /// <param name="bodyHMTL">Corpo em HTML:</param>
        /// <param name="smtpNetworkSettings"></param>
        /// <param name="errorMessage">The Error Message</param>
        /// <returns></returns>
        public static Boolean SendMail(String from, String friendlyName, String to, String subject, String bodyHMTL, SmtpNetworkElement smtpNetworkSettings, out String errorMessage)
        {
            try
            {
                var objMail = new MailMessage();

                // Add To
                objMail.To.Add(to);

                // Add Subject
                objMail.Subject = subject;

                //// First we create the Plain Text Part
                //AlternateView plainView = AlternateView.CreateAlternateViewFromString("Este é um texto sem conteúdo, vistos por aqueles clientes que não suportam html", null, "text/plain");            
                //objMail.AlternateViews.Add(plainView);

                objMail.IsBodyHtml = true;
                objMail.Body = bodyHMTL;

                // Information from Web.Config            
                var configurationFile = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.Url.AbsolutePath);//System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
                var mailSettings = configurationFile.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;

                var port = 25;
                var host = String.Empty;
                var password = String.Empty;

                var userName = String.Empty;
                var defaultCredentials = false;
                var enableSsl = false;

                if (smtpNetworkSettings != null && !String.IsNullOrWhiteSpace(smtpNetworkSettings.Host))
                {
                    port = smtpNetworkSettings.Port;
                    host = smtpNetworkSettings.Host;
                    password = smtpNetworkSettings.Password;
                    userName = smtpNetworkSettings.UserName;
                    enableSsl = smtpNetworkSettings.EnableSsl;
                }
                else if (mailSettings != null)
                {
                    port = mailSettings.Smtp.Network.Port;
                    host = mailSettings.Smtp.Network.Host;
                    password = mailSettings.Smtp.Network.Password;
                    userName = mailSettings.Smtp.Network.UserName;
                    defaultCredentials = mailSettings.Smtp.Network.DefaultCredentials;
                    enableSsl = mailSettings.Smtp.Network.EnableSsl;
                }

                // Add From
                if (String.IsNullOrEmpty(from))
                {
                    if (mailSettings != null)
                    {
                        objMail.From = new MailAddress(mailSettings.Smtp.From);
                    }
                }
                else
                {
                    objMail.From = !String.IsNullOrEmpty(friendlyName) ? new MailAddress(from, friendlyName) : new MailAddress(from);
                }

                var smtp = new SmtpClient
                {
                    Port = port,
                    Host = host,
                    EnableSsl = enableSsl,
                    UseDefaultCredentials = defaultCredentials,
                    Credentials = new NetworkCredential(userName, password)
                };

                smtp.Send(objMail);
                errorMessage = "Message sent Successfully!";
                return true;
            }
            catch (SmtpException ex)
            {
                errorMessage = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// Method to send mail
        /// </summary>
        /// <param name="from">From.</param>
        /// <param name="friendlyName">Joselito Sem ...</param>
        /// <param name="lstTo">The LST to.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="bodyHMTL">The body HMTL.</param>
        /// <param name="pathAttachment">"c:\\temp\\example.txt"</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public static bool SendMail(String from, String friendlyName, List<String> lstTo, String subject, String bodyHMTL, String pathAttachment, out String errorMessage)
        {
            try
            {
                var objMail = new MailMessage();

                // Add To
                if (lstTo != null)
                {
                    if (lstTo.Count > 0)
                    {
                        foreach (var to in lstTo)
                        {
                            objMail.To.Add(to);
                        }
                    }
                }

                // Add Subject
                objMail.Subject = subject;

                // Add an attachment from the filesystem
                if (!String.IsNullOrEmpty(pathAttachment))
                    objMail.Attachments.Add(new Attachment(pathAttachment));

                objMail.IsBodyHtml = true;
                objMail.Body = bodyHMTL;

                // Information from Web.Config
                var configurationFile = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.Url.AbsolutePath);//System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
                var mailSettings = configurationFile.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
                var port = 25;
                var host = String.Empty;
                var password = String.Empty;
                var userName = String.Empty;
                var defaultCredentials = false;
                var enableSsl = false;

                if (mailSettings != null)
                {
                    port = mailSettings.Smtp.Network.Port;
                    host = mailSettings.Smtp.Network.Host;
                    password = mailSettings.Smtp.Network.Password;
                    userName = mailSettings.Smtp.Network.UserName;
                    defaultCredentials = mailSettings.Smtp.Network.DefaultCredentials;
                    enableSsl = mailSettings.Smtp.Network.EnableSsl;
                }

                // Add From
                if (String.IsNullOrEmpty(from))
                {
                    if (mailSettings != null) objMail.From = new MailAddress(mailSettings.Smtp.From);
                }
                else
                {
                    objMail.From = !String.IsNullOrEmpty(friendlyName) ? new MailAddress(from, friendlyName) : new MailAddress(from);
                }

                var smtp = new SmtpClient
                {
                    Port = port,
                    Host = host,
                    EnableSsl = enableSsl,
                    UseDefaultCredentials = defaultCredentials,
                    Credentials = new NetworkCredential(userName, password)
                };

                smtp.Send(objMail);
                errorMessage = "Message send Successfully!";
                return true;
            }
            catch (SmtpException ex)
            {
                HttpContext.Current.AddError(ex);
                errorMessage = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// Method to Send mail with images
        /// </summary>
        /// <param name="from">From.</param>
        /// <param name="friendlyName">Name of the friendly.</param>
        /// <param name="to">To.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="bodyHMTL">The body HMTL.</param>
        /// <param name="cids">The cids.</param>
        /// <param name="imagesPath">The images path.</param>
        /// <param name="smtpNetworkSettings"></param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public static Boolean SendMailWithImages(String from, String friendlyName, String to, String subject, String bodyHMTL, List<String> cids, List<String> imagesPath, SmtpNetworkElement smtpNetworkSettings, out String errorMessage)
        {
            try
            {
                var objMail = new MailMessage();

                // Add To
                objMail.To.Add(to);

                // Add Subject
                objMail.Subject = subject;

                // Add Images in Body HTML
                if (cids.Count > 0)
                {
                    //then we create the Html part
                    //to embed images, we need to use the prefix 'cid' in the img src value
                    //the cid value will map to the Content-Id of a Linked resource.
                    //thus <img src='cid:companylogo'> will map to a LinkedResource with a ContentId of 'companylogo'
                    AlternateView htmlView = AlternateView.CreateAlternateViewFromString(bodyHMTL, null, "text/html");

                    for (int i = 0; i < cids.Count; i++)
                    {
                        //create the LinkedResource (embedded image)
                        var img = new LinkedResource(imagesPath[i]) { ContentId = cids[i] };

                        //add the LinkedResource to the appropriate view
                        htmlView.LinkedResources.Add(img);
                    }
                    objMail.AlternateViews.Add(htmlView);
                }

                objMail.IsBodyHtml = true;
                objMail.Body = bodyHMTL;

                // Information from Web.Config
                var configurationFile = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.Url.AbsolutePath);//System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath
                var mailSettings = configurationFile.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;

                var port = 25;
                var host = String.Empty;
                var password = String.Empty;
                var userName = String.Empty;
                var defaultCredentials = false;
                var enableSsl = false;

                if (smtpNetworkSettings != null)
                {
                    port = smtpNetworkSettings.Port;
                    host = smtpNetworkSettings.Host;
                    password = smtpNetworkSettings.Password;
                    userName = smtpNetworkSettings.UserName;
                    enableSsl = smtpNetworkSettings.EnableSsl;
                }
                else if (mailSettings != null)
                {
                    port = mailSettings.Smtp.Network.Port;
                    host = mailSettings.Smtp.Network.Host;
                    password = mailSettings.Smtp.Network.Password;
                    userName = mailSettings.Smtp.Network.UserName;
                    defaultCredentials = mailSettings.Smtp.Network.DefaultCredentials;
                    enableSsl = mailSettings.Smtp.Network.EnableSsl;
                }


                // Add From
                if (String.IsNullOrEmpty(from))
                {
                    if (!String.IsNullOrEmpty(friendlyName))
                    {
                        if (mailSettings != null)
                        {
                            objMail.From = new MailAddress(mailSettings.Smtp.From, friendlyName);
                        }
                    }
                    else if (mailSettings != null)
                    {
                        objMail.From = new MailAddress(mailSettings.Smtp.From);
                    }
                }
                else
                {
                    objMail.From = !String.IsNullOrEmpty(friendlyName) ? new MailAddress(from, friendlyName) : new MailAddress(from);
                }

                var smtp = new SmtpClient
                {
                    Port = port,
                    Host = host,
                    EnableSsl = enableSsl,
                    UseDefaultCredentials = defaultCredentials,
                    Credentials = new NetworkCredential(userName, password)
                };

                smtp.Send(objMail);
                errorMessage = "Message send Successfully!";
                return true;
            }
            catch (SmtpException ex)
            {
                HttpContext.Current.AddError(ex);
                errorMessage = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// Method to return screen scrape the html
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static String ScreenScrapeHtml(String url)
        {
            var objRequest = WebRequest.Create(url);
            var sr = new StreamReader(objRequest.GetResponse().GetResponseStream(), Encoding.UTF8);
            var result = sr.ReadToEnd();
            sr.Close();
            return result;
        }

        #endregion [ Métodos para envio de Email ]

        #region [ Métodos para se Trabalhar com URLs ]

        /// <summary>
        /// Returns the URL formated.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="title">The title.</param>
        /// <returns></returns>
        public static String ReturnUrlFormated(String path, String title)
        {
            if (String.IsNullOrEmpty(title)) return "";
            //change diacritic characters to non-diacritic ones
            title = Regex.Replace(title.Normalize(NormalizationForm.FormD), @"[^A-Za-z 0-9 \.,\?'""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*", string.Empty).Trim();
            // remove entities
            title = Regex.Replace(title, @"&\w+;", "");
            // remove anything that is not letters, numbers, dash, or space
            title = Regex.Replace(title, @"[^A-Za-z0-9\-\s]", "");
            // remove any leading or trailing spaces left over
            title = title.Trim();
            // replace spaces with single dash
            title = Regex.Replace(title, @"\s+", "-");
            // if we end up with multiple dashes, collapse to single dash            
            title = Regex.Replace(title, @"\-{2,}", "-");
            // make it all lower case
            title = title.ToLower();
            //// if it's too long, clip it
            //if (title.Length > 80)
            //    title = title.Substring(0, 79);
            // remove trailing dash, if there is one
            if (title.EndsWith("-"))
                title = title.Substring(0, title.Length - 1);

            return path + title;
        }

        #endregion [ Métodos para se Trabalhar com URLs ]

        #region [ Métodos para se Trabalha com Languages ]

        /// <summary>
        /// Gets the resource language.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public static ResourceLanguage GetResourceLanguage(String name)
        {
            return new ResourceLanguage(name);
        }

        #endregion [ Métodos para se Trabalha com Languages ]

        #region [ Métodos para se Trabalhar com os Parametros cadastrados no Web.Config ]

        /// <summary>
        /// Gets the limite de itens menu topo.
        /// </summary>
        public static String LimiteDeItensMenuTopo
        {
            get
            {
                try
                {
                    return !String.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["LimiteDeItensMenuTopo"])
                    ? ConfigurationManager.AppSettings["LimiteDeItensMenuTopo"]
                    : "0";
                }
                catch (Exception)
                {
                    throw new ConfigurationErrorsException("Limite de Itens do Menu Topo Não foi Encontrado! - Key[LimiteDeItensMenuTopo]");
                }
            }
        }

        /// <summary>
        /// Gets the limite de itens menu rodape.
        /// </summary>
        public static String LimiteDeItensMenuRodape
        {
            get
            {
                try
                {
                    return !String.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["LimiteDeItensMenuRodape"])
                               ? ConfigurationManager.AppSettings["LimiteDeItensMenuRodape"]
                               : "0";
                }
                catch (Exception)
                {
                    throw new ConfigurationErrorsException("Limite de Itens do Menu Rodape Não foi Encontrado! - Key[LimiteDeItensMenuRodape]");
                }
            }
        }

        #endregion [ Métodos para se Trabalhar com os Parametros cadastrados no Web.Config ]

        #region [ Métodos para se trabalhar com Validadores ]

        public static Boolean ValidationGroupIsValid(Page page, String validationGroup, ref String controlInvalid, ref String errorMessage, ref String group)
        {
            var result = false;
            page.Validate(validationGroup);
            if (!page.IsValid)
            {
                // Recupera a Mensagem de Erro do Controle Invalidado
                var validators = page.GetValidators(validationGroup);
                if (validators.Count > 0)
                {
                    var invalidControl = validators.Cast<BaseValidator>().ToList().FirstOrDefault(control => !control.IsValid);
                    if (invalidControl != null && !String.IsNullOrEmpty(invalidControl.ErrorMessage))
                    {
                        errorMessage = invalidControl.ErrorMessage;
                        controlInvalid = invalidControl.ControlToValidate;
                        group = validationGroup;
                    }
                }
            }
            else
            {
                result = page.IsValid;
            }
            return result;
        }

        public static Boolean ValidationGroupIsValid(Page page, String validationGroup)
        {
            var result = false;
            page.Validate(validationGroup);
            if (!page.IsValid)
            {
                // Recupera a Mensagem de Erro do Controle Invalidado
                var validators = page.GetValidators(validationGroup);
                if (validators.Count > 0)
                {
                    var invalidControl = validators.Cast<BaseValidator>().ToList().FirstOrDefault(control => !control.IsValid);
                    if (invalidControl != null)
                    {
                        return false;
                    }
                }
            }
            else
            {
                result = page.IsValid;
            }
            return result;
        }

        #endregion [ Métodos para se trabalhar com Validadores ]

        #region [ Métodos de Criptografia ]

        /// <summary>
        /// This function takes the data and key as strings and returns the hash as a hexadecimal value
        /// Its is used in Authorize.net to get the fingerprint hash
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string HMAC_MD5(string key, string value)
        {
            // The first two lines take the input values and convert them from strings to Byte arrays
            byte[] HMACkey = (new System.Text.ASCIIEncoding()).GetBytes(key);
            byte[] HMACdata = (new System.Text.ASCIIEncoding()).GetBytes(value);

            // create a HMACMD5 object with the key set
            HMACMD5 myhmacMD5 = new HMACMD5(HMACkey);

            //calculate the hash (returns a byte array)
            byte[] HMAChash = myhmacMD5.ComputeHash(HMACdata);

            //loop through the byte array and add append each piece to a string to obtain a hash string
            string fingerprint = "";
            for (int i = 0; i < HMAChash.Length; i++)
            {
                fingerprint += HMAChash[i].ToString("x").PadLeft(2, '0');
            }

            return fingerprint;
        }

        #endregion [ Métodos de Criptografia ]
    }

    public class ResourceLanguage
    {
        public String Name { get; set; }
        public String DisplayName { get; set; }

        public ResourceLanguage(String name)
        {
            try
            {
                var cultureInfo = new CultureInfo(name);
                this.Name = cultureInfo.Name;
                this.DisplayName = cultureInfo.DisplayName;
            }
            catch
            {
                this.Name = name;
                this.DisplayName = name;
            }
        }

        public override String ToString()
        {
            return this.DisplayName;
        }
    }

    public class ReturnJS
    {
        public TypeMessage Type { get; set; }
        public String Message { get; set; }
        public ReturnJS(TypeMessage _type, String _message)
        {
            Type = _type;
            Message = _message;
        }
        public new String ToString()
        {
            return "{ type: " + ((int)Type) + ", Message: '" + Message + "' }";
        }
    }

    public enum TypeMessage
    {
        Error = 1,
        Success = 2
    }

    public enum SortingProducts
    {
        NameAz = 1,
        NameZa = 2,
        LowestPrice = 3,
        HighestPrice = 4
    }
}
